home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
map.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
6KB
|
285 lines
/*
* @(#)map.c 1.2 3/18/87
*/
/* Copyright 1986 Norm Hutchinson. May not be used for any *
* purpose without written permission from the author. */
#include "assert.h"
#include "system.h"
#include "map.h"
#define INITIALSIZE 4
#define HASH(key, map) (((key) ^ ((key) >> 4)) & map->maxIndex)
static void CheckOutHashTable();
Map Map_Create()
{
register int i;
register Map m;
m = (Map) malloc(sizeof(MapRecord));
m->maxIndex = INITIALSIZE - 1;
m->maxCount = m->maxIndex - (m->maxIndex >> 2); /* Max fill 87.5 % */
m->count = 0;
m->table = (TEPtr) malloc(INITIALSIZE * sizeof(TE));
for (i = 0; i < INITIALSIZE; i++) {
m->table[i].key = NIL;
}
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
return(m);
}
Map Map_CreateSized(fCount)
int fCount;
{
register int i;
register Map m;
assert(fCount > 0);
m = (Map) malloc(sizeof(MapRecord));
for (i = 1; i < fCount; i += i);
m->maxIndex = i - 1;
m->maxCount = m->maxIndex - (m->maxIndex >> 2); /* Max fill 87.5 % */
m->count = 0;
m->table = (TEPtr) malloc((unsigned)((m->maxIndex+1) * sizeof(TE)));
for (i = 0; i <= m->maxIndex ; i++) {
m->table[i].key = NIL;
}
# ifdef lint
CheckOutHashTable(m);
#endif
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
return(m);
}
void Map_Destroy(m)
register Map m;
{
if (m == (Map) NULL) return;
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
free((char *)m->table);
free((char *)m);
}
static void ExpandHashTable(m)
register Map m;
{
register TE *nh, *oe, *ne;
register int oldHashTableSize = m->maxIndex + 1, i;
register int key;
int index;
m->maxIndex = oldHashTableSize * 2 - 1;
m->maxCount = m->maxIndex - (m->maxIndex >> 2);
nh = (TEPtr) malloc((unsigned)(oldHashTableSize * 2 * sizeof(TE)));
for (i = 0; i <= m->maxIndex; i++) nh[i].key = NIL;
for (i = 0; i < oldHashTableSize; i++) {
oe = &m->table[i];
key = oe->key;
if (key == NIL) continue;
index = HASH(key, m);
while (1) {
ne = &nh[index];
if (ne->key == NIL) {
ne->key = oe->key;
ne->value = oe->value;
break;
} else {
assert(ne->key !=key);
index++;
if (index > m->maxIndex) index = 0;
}
}
}
free((char *)m->table);
m->table = nh;
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
}
int Map_Lookup(m, key)
register Map m;
register int key;
{
register int index = HASH(key, m);
register TEPtr e;
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
while (1) {
e = &m->table[index];
if (e->key == NIL) { /* we did not find it */
return (NIL);
} else if (e->key == key) {
return (e->value);
}
if (++index > m->maxIndex) index = 0;
}
}
void Map_Delete(m, key)
register Map m;
register int key;
/* Remove the entry, if it is there */
{
register int index = HASH(key, m);
register int value;
register TEPtr e;
while (1) {
e = &m->table[index];
if (e->key == NIL) { /* we did not find it */
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
return;
}
if (e->key == key) {
/* Found it, now remove it */
m->count--;
e->key = NIL;
e->value = NIL;
while (1) {
/* rehash until we reach nil again */
if (++index > m->maxIndex) index = 0;
e = & m->table[index];
key = e->key;
if (key == NIL) {
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
return;
}
/* rehashing is done by removing then reinserting */
value = e->value;
e->key = e->value = NIL;
m->count--;
Map_Insert(m, key, value);
}
}
if (++index > m->maxIndex) index = 0;
}
}
void Map_Insert(m, key, value)
register Map m;
register int key, value;
{
register int index;
register TEPtr e;
assert(key != NIL);
if (m->count >= m->maxCount) ExpandHashTable(m);
index = HASH(key, m);
while (1) {
e = &m->table[index];
if (e->key == NIL) { /* put it here */
e->key = key;
e->value = value;
m->count++;
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
return;
} else if (e->key == key) {
e->value = value;
#ifdef DEBUGMAP
CheckOutHashTable(m);
#endif DEBUGMAP
return;
}
if (++index > m->maxIndex) index = 0;
}
}
int Map_FindNext(m, startIndex, keyPtr, valuePtr)
register Map m;
int *startIndex;
int *keyPtr, *valuePtr;
{
register int i;
register TEPtr e;
for (i = *startIndex; i <= m->maxIndex; i++) {
e = &m->table[i];
if (e->key != NIL) {
*keyPtr = e->key;
*valuePtr = e->value;
*startIndex = i + 1;
return(1);
}
}
*keyPtr = NIL;
*valuePtr = NIL;
*startIndex = -1;
return(0);
}
void Map_Print(m)
register Map m;
{
int key, value, index;
printf(
"\nDump of map @ 0x%05x, %d entr%s, current max %d\nIndex\tKey\t\tValue\n",
m, m->count, m->count == 1 ? "y" : "ies", m->maxCount);
for (index = 0; index <= m->maxIndex; index++) {
key = m->table[index].key;
value = m->table[index].value;
printf("%3d\t0x%08.8x\t0x%08.8x\n", index, key, value);
}
}
static void CheckOutHashTable(m)
register Map m;
{
register int i;
register TEPtr realElement, e;
register int index, firstIndex, count;
count = 0;
for (i = 0; i <= m->maxIndex; i++) {
realElement = &m->table[i];
if (realElement->key != NIL) {
count++;
index = HASH(realElement->key, m);
firstIndex = index;
while (1) {
e = &m->table[index];
if (e->key == NIL) { /* we did not find it */
break;
} else if (e->key == realElement->key) {
break;
} else {
index++;
if (index > m->maxIndex) index = 0;
if (index == firstIndex) {
index = -1;
break;
}
}
}
if (index == -1 || e->key != realElement->key) {
fprintf(stderr,
"Map problem: Key 0x%x, rightIndex %d, realIndex %d value 0x%x\n",
realElement->key, firstIndex, index, realElement->value);
Map_Print(m);
}
}
}
if (count != m->count) {
fprintf(stderr,
"Map problem: Should have %d entries, but found %d.\n", m->count,
count);
Map_Print(m);
}
}